package com.ls.compress;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.zip.DataFormatException;
import java.util.zip.Deflater;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
import java.util.zip.Inflater;

import org.apache.commons.compress.compressors.bzip2.BZip2CompressorInputStream;
import org.apache.commons.compress.compressors.bzip2.BZip2CompressorOutputStream;
import org.apache.commons.compress.compressors.deflate.DeflateCompressorInputStream;
import org.apache.commons.compress.compressors.deflate.DeflateCompressorOutputStream;
import org.apache.commons.compress.compressors.deflate.DeflateParameters;
import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream;
import org.apache.commons.compress.compressors.gzip.GzipCompressorOutputStream;
import org.apache.commons.compress.compressors.xz.XZCompressorInputStream;
import org.apache.commons.compress.compressors.xz.XZCompressorOutputStream;
import org.apache.commons.io.IOUtils;
import org.junit.Test;
import org.tukaani.xz.LZMA2Options;
import org.tukaani.xz.XZInputStream;
import org.tukaani.xz.XZOutputStream;
import org.xerial.snappy.Snappy;

import net.jpountz.lz4.LZ4BlockInputStream;
import net.jpountz.lz4.LZ4BlockOutputStream;
import net.jpountz.lz4.LZ4Compressor;
import net.jpountz.lz4.LZ4Factory;
import net.jpountz.lz4.LZ4FastDecompressor;

public class Compress{
	
	//lz4压缩
	public static byte[] lz4Compress(byte[] data) throws IOException {
	    LZ4Factory factory = LZ4Factory.fastestInstance();
	    ByteArrayOutputStream byteOutput = new ByteArrayOutputStream();
	    LZ4Compressor compressor = factory.fastCompressor();
	    LZ4BlockOutputStream compressedOutput = new LZ4BlockOutputStream(byteOutput, 8192, compressor);
	    compressedOutput.write(data);
	    compressedOutput.close();
	    return byteOutput.toByteArray();
	}
	 
	public static byte[] lz4Decompress(byte[] data) throws IOException {
	    LZ4Factory factory = LZ4Factory.fastestInstance();
	    ByteArrayOutputStream baos = new ByteArrayOutputStream(8192);
	    LZ4FastDecompressor decompresser = factory.fastDecompressor();
	    LZ4BlockInputStream lzis = new LZ4BlockInputStream(new ByteArrayInputStream(data), decompresser);
	    int count;
	    byte[] buffer = new byte[8192];
	    while ((count = lzis.read(buffer)) != -1) {
	        baos.write(buffer, 0, count);
	    }
	    lzis.close();
	    return baos.toByteArray();
	}
	 
	//JDK deflate 压缩
	public static byte[] jdkDeflaterCompress(byte[] data) throws IOException {
	    Deflater deflater = new Deflater();
	    deflater.setLevel(1);
	    deflater.setInput(data);
	    ByteArrayOutputStream outputStream = new ByteArrayOutputStream(8192);
	    deflater.finish();
	    while (!deflater.finished()) {
	        byte[] buffer = new byte[8192];
	        int count = deflater.deflate(buffer);
	        outputStream.write(buffer, 0, count);
	    }
	    outputStream.close();
	    byte[] output = outputStream.toByteArray();
	    return output;
	}
	 
	public static byte[] jdkInflaterDecompress(byte[] data) throws IOException, DataFormatException {
	    Inflater inflater = new Inflater();
	    inflater.setInput(data);
	    ByteArrayOutputStream outputStream = new ByteArrayOutputStream(8192);
	    while (!inflater.finished()) {
	        byte[] buffer = new byte[8192];
	        int count = inflater.inflate(buffer);
	        outputStream.write(buffer, 0, count);
	    }
	    outputStream.close();
	    byte[] output = outputStream.toByteArray();
	    return output;
	} 
	 
	//JDK GIP压缩
	public static final byte[] jdkGzip(byte[] data) {
	    ByteArrayOutputStream out = new ByteArrayOutputStream(8192);
	    GZIPOutputStream gzip = null;
	    try {
	        gzip = new GZIPOutputStream(out);
	        gzip.write(data);
	        gzip.finish();
	        return out.toByteArray();
	    } catch (IOException e) {
	        return null;
	    } finally {
	        IOUtils.closeQuietly(gzip);
	    }
	}
	 
	public static final byte[] jdkGunzip(byte[] bytes) throws IOException {
	    if (bytes == null || bytes.length == 0) {
	        return null;
	    }
	    ByteArrayOutputStream baos = new ByteArrayOutputStream(8192);
	    GZIPInputStream gis = new GZIPInputStream(new ByteArrayInputStream(bytes));
	    int count;
	    byte[] buffer = new byte[8192];
	    while ((count = gis.read(buffer)) != -1) {
	        baos.write(buffer, 0, count);
	    }
	    gis.close();
	    return baos.toByteArray();
	}
	
	//xz压缩
	public static byte[] xzCompress(byte[] data) throws IOException {
	    LZMA2Options options = new LZMA2Options();
	    // options.setMode(LZMA2Options.MODE_NORMAL);
	    // options.setDepthLimit(9);
	    // options.setLc(4);
	    // options.setPb(0);
	    // options.setPreset(8);
	    // options.setNiceLen(64);
	    ByteArrayOutputStream outputStream = new ByteArrayOutputStream(8192);
	    XZOutputStream out = new XZOutputStream(outputStream, options);
	    out.write(data);
	    out.finish();
	    out.close();
	    return outputStream.toByteArray();
	}
	 
	public static byte[] xzDecompress(byte[] data) throws IOException, DataFormatException {
	    ByteArrayOutputStream baos = new ByteArrayOutputStream(8192);
	    XZInputStream xzis = new XZInputStream(new ByteArrayInputStream(data));
	    int count;
	    byte[] buffer = new byte[8192];
	    while ((count = xzis.read(buffer)) != -1) {
	        baos.write(buffer, 0, count);
	    }
	    xzis.close();
	    return baos.toByteArray();
	}
	 
	//bzip2压缩
	public static byte[] commonBzip2Decompress(byte[] data) throws IOException {
	    ByteArrayOutputStream baos = new ByteArrayOutputStream(8192);
	    BZip2CompressorInputStream bcis = new BZip2CompressorInputStream(new ByteArrayInputStream(data));
	    int count;
	    byte[] buffer = new byte[8192];
	    while ((count = bcis.read(buffer)) != -1) {
	        baos.write(buffer, 0, count);
	    }
	    bcis.close();
	    return baos.toByteArray();
	}
	 
	public static byte[] commonBzip2Compress(byte[] data) throws IOException {
	    ByteArrayOutputStream baos = new ByteArrayOutputStream(8192);
	    BZip2CompressorOutputStream bcos = new BZip2CompressorOutputStream(baos);
	    bcos.write(data);
	    bcos.close();
	    return baos.toByteArray();
	}
	 
	//apache common deflate 压缩
	public static byte[] commonDeflaterCompress(byte[] data) throws IOException {
	    ByteArrayOutputStream baos = new ByteArrayOutputStream(8192);
	    DeflateParameters dp = new DeflateParameters();
	    dp.setCompressionLevel(5);
	    DeflateCompressorOutputStream dcos = new DeflateCompressorOutputStream(baos, dp);
	    dcos.write(data);
	    dcos.close();
	    return baos.toByteArray();
	}
	 
	public static byte[] commonDeflaterDecompress(byte[] data) throws IOException {
	    ByteArrayOutputStream baos = new ByteArrayOutputStream(8192);
	    DeflateCompressorInputStream dcis = new DeflateCompressorInputStream(new ByteArrayInputStream(data));
	    int count;
	    byte[] buffer = new byte[8192];
	    while ((count = dcis.read(buffer)) != -1) {
	        baos.write(buffer, 0, count);
	    }
	    dcis.close();
	    return baos.toByteArray();
	}
	 
	//apache common gzip 压缩
	public static byte[] commonGzipCompress(byte[] data) throws IOException {
	    ByteArrayOutputStream baos = new ByteArrayOutputStream(512);
	    GzipCompressorOutputStream gcos = new GzipCompressorOutputStream(baos);
	    gcos.write(data);
	    gcos.close();
	    return baos.toByteArray();
	}
	 
	public static byte[] commonGzipDecompress(byte[] data) throws IOException {
	    ByteArrayOutputStream baos = new ByteArrayOutputStream(512);
	    GzipCompressorInputStream gcis = new GzipCompressorInputStream(new ByteArrayInputStream(data));
	    int count;
	    byte[] buffer = new byte[8192];
	    while ((count = gcis.read(buffer)) != -1) {
	        baos.write(buffer, 0, count);
	    }
	    gcis.close();
	    return baos.toByteArray();
	}
	 
	//apache xz 压缩
	public static byte[] commonXzCompress(byte[] data) throws IOException {
	    ByteArrayOutputStream baos = new ByteArrayOutputStream(8192);
	    XZCompressorOutputStream pcos = new XZCompressorOutputStream(baos);
	    pcos.write(data);
	    pcos.close();
	    return baos.toByteArray();
	}
	 
	public static byte[] commonXzDecompress(byte[] data) throws IOException {
	    ByteArrayOutputStream baos = new ByteArrayOutputStream(8192);
	    XZCompressorInputStream xzis = new XZCompressorInputStream(new ByteArrayInputStream(data));
	    int count;
	    byte[] buffer = new byte[8192];
	    while ((count = xzis.read(buffer)) != -1) {
	        baos.write(buffer, 0, count);
	    }
	    xzis.close();
	    return baos.toByteArray();
	}
	 
	//snappy 压缩
	public static byte[] snappyCompress(byte[] data) throws IOException {
	    return Snappy.compress(data);
	}
	 
	public static byte[] snappyDecompress(byte[] data) throws IOException {
	    return Snappy.uncompress(data);
	}
	
	
//	@Test
	public void testAxz() throws IOException {
		StringBuffer  a=new StringBuffer();
		for(int i=0;i<100;i++){
			a.append("uap"+i);
		}
		byte[] originbyte = a.toString().getBytes("UTF-8");
		System.out.println("压缩前大小 :"+originbyte.length);
		long startTime = System.currentTimeMillis();
		byte[] afterbyte = commonXzCompress(originbyte);
		long endTime = System.currentTimeMillis();
		System.out.println("压缩后大小 : "+afterbyte.length);
		byte[] decode = commonXzDecompress(afterbyte);
		long endTime2 = System.currentTimeMillis();
		System.out.println(new String(decode,"UTF-8"));
		System.out.println("压缩时间"+(endTime-startTime));
		System.out.println("解压时间"+(endTime2-endTime));
	}
	
//	@Test
	public void testSnappy() throws IOException {
		StringBuffer  a=new StringBuffer();
		for(int i=0;i<100;i++){
			a.append("uap"+i);
		}
		byte[] originbyte = a.toString().getBytes("UTF-8");
		System.out.println("压缩前大小 :"+originbyte.length);
		long startTime = System.currentTimeMillis();
		byte[] afterbyte = snappyCompress(originbyte);
		long endTime = System.currentTimeMillis();
		System.out.println("压缩后大小 : "+afterbyte.length);
		byte[] decode = snappyDecompress(afterbyte);
		long endTime2 = System.currentTimeMillis();
		System.out.println(new String(decode,"UTF-8"));
		System.out.println("压缩时间"+(endTime-startTime));
		System.out.println("解压时间"+(endTime2-endTime));
	}
	
//	@Test
	public void testagz() throws IOException {
		StringBuffer  a=new StringBuffer();
		for(int i=0;i<100;i++){
			a.append("uap"+i);
		}
		byte[] originbyte = a.toString().getBytes("UTF-8");
		System.out.println("压缩前大小 :"+originbyte.length);
		long startTime = System.currentTimeMillis();
		byte[] afterbyte = commonGzipCompress(originbyte);
		long endTime = System.currentTimeMillis();
		System.out.println("压缩后大小 : "+afterbyte.length);
		byte[] decode = commonGzipDecompress(afterbyte);
		long endTime2 = System.currentTimeMillis();
		System.out.println(new String(decode,"UTF-8"));
		System.out.println("压缩时间"+(endTime-startTime));
		System.out.println("解压时间"+(endTime2-endTime));
	}
	
//	@Test
	public void testadez() throws IOException {
		StringBuffer  a=new StringBuffer();
		for(int i=0;i<100;i++){
			a.append("uap"+i);
		}
		byte[] originbyte = a.toString().getBytes("UTF-8");
		System.out.println("压缩前大小 :"+originbyte.length);
		long startTime = System.currentTimeMillis();
		byte[] afterbyte = commonDeflaterCompress(originbyte);
		long endTime = System.currentTimeMillis();
		System.out.println("压缩后大小 : "+afterbyte.length);
		byte[] decode = commonDeflaterDecompress(afterbyte);
		long endTime2 = System.currentTimeMillis();
		System.out.println(new String(decode,"UTF-8"));
		System.out.println("压缩时间"+(endTime-startTime));
		System.out.println("解压时间"+(endTime2-endTime));
	}
	
//	@Test
	public void testabz2() throws IOException {
		StringBuffer  a=new StringBuffer();
		for(int i=0;i<100;i++){
			a.append("uap"+i);
		}
		byte[] originbyte = a.toString().getBytes("UTF-8");
		System.out.println("压缩前大小 :"+originbyte.length);
		long startTime = System.currentTimeMillis();
		byte[] afterbyte = commonBzip2Compress(originbyte);
		long endTime = System.currentTimeMillis();
		System.out.println("压缩后大小 : "+afterbyte.length);
		byte[] decode = commonBzip2Decompress(afterbyte);
		long endTime2 = System.currentTimeMillis();
		System.out.println(new String(decode,"UTF-8"));
		System.out.println("压缩时间"+(endTime-startTime));
		System.out.println("解压时间"+(endTime2-endTime));
	}
	
//	@Test
	public void testaxz() throws IOException, DataFormatException {
		StringBuffer  a=new StringBuffer();
		for(int i=0;i<100;i++){
			a.append("uap"+i);
		}
		byte[] originbyte = a.toString().getBytes("UTF-8");
		System.out.println("压缩前大小 :"+originbyte.length);
		long startTime = System.currentTimeMillis();
		byte[] afterbyte = xzCompress(originbyte);
		long endTime = System.currentTimeMillis();
		System.out.println("压缩后大小 : "+afterbyte.length);
		byte[] decode = xzDecompress(afterbyte);
		long endTime2 = System.currentTimeMillis();
		System.out.println(new String(decode,"UTF-8"));
		System.out.println("压缩时间"+(endTime-startTime));
		System.out.println("解压时间"+(endTime2-endTime));
	}
	
//	@Test
	public void testjdkgz() throws IOException, DataFormatException {
		StringBuffer  a=new StringBuffer();
		for(int i=0;i<100;i++){
			a.append("uap"+i);
		}
		byte[] originbyte = a.toString().getBytes("UTF-8");
		System.out.println("压缩前大小 :"+originbyte.length);
		long startTime = System.currentTimeMillis();
		byte[] afterbyte = jdkGzip(originbyte);
		long endTime = System.currentTimeMillis();
		System.out.println("压缩后大小 : "+afterbyte.length);
		byte[] decode = jdkGunzip(afterbyte);
		long endTime2 = System.currentTimeMillis();
		System.out.println(new String(decode,"UTF-8"));
		System.out.println("压缩时间"+(endTime-startTime));
		System.out.println("解压时间"+(endTime2-endTime));
	}
	
//	@Test
	public void testlz() throws IOException, DataFormatException {
		StringBuffer  a=new StringBuffer();
		for(int i=0;i<100;i++){
			a.append("uap"+i);
		}
		byte[] originbyte = a.toString().getBytes("UTF-8");
		System.out.println("压缩前大小 :"+originbyte.length);
		long startTime = System.currentTimeMillis();
		byte[] afterbyte = jdkDeflaterCompress(originbyte);
		long endTime = System.currentTimeMillis();
		System.out.println("压缩后大小 : "+afterbyte.length);
		byte[] decode = jdkInflaterDecompress(afterbyte);
		long endTime2 = System.currentTimeMillis();
		System.out.println(new String(decode,"UTF-8"));
		System.out.println("压缩时间"+(endTime-startTime));
		System.out.println("解压时间"+(endTime2-endTime));
	}
	
	@Test
	public void testjdkde() throws IOException, DataFormatException {
		StringBuffer  a=new StringBuffer();
		for(int i=0;i<100;i++){
			a.append("uap"+i);
		}
		byte[] originbyte = a.toString().getBytes("UTF-8");
		System.out.println("压缩前大小 :"+originbyte.length);
		long startTime = System.currentTimeMillis();
		byte[] afterbyte = lz4Compress(originbyte);
		long endTime = System.currentTimeMillis();
		System.out.println("压缩后大小 : "+afterbyte.length);
		byte[] decode = lz4Decompress(afterbyte);
		long endTime2 = System.currentTimeMillis();
		System.out.println(new String(decode,"UTF-8"));
		System.out.println("压缩时间"+(endTime-startTime));
		System.out.println("解压时间"+(endTime2-endTime));
	}
}